#ifndef STORAGE_ENGINE_H
#define STORAGE_ENGINE_H

#define _POSIX_C_SOURCE 200112L

#include "../../include/gudb.h"
#include "file_system.h"
#include "../memory/memory_manager.h"
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>

// Page and node configuration
#define PAGE_SIZE 4096
#define MAX_KEY_SIZE 256
#define MAX_VALUE_SIZE 1024
#define MAX_KEYS_PER_PAGE ((PAGE_SIZE - 64) / (MAX_KEY_SIZE + 8))
#define MAX_CHILDREN_PER_PAGE (MAX_KEYS_PER_PAGE + 1)

// Node types
#define NODE_TYPE_LEAF 1
#define NODE_TYPE_INNER 2
#define NODE_TYPE_DELTA 3

// Delta record types
#define DELTA_INSERT 1
#define DELTA_DELETE 2
#define DELTA_UPDATE 3
#define DELTA_SPLIT 4
#define DELTA_MERGE 5

// Key comparison result
#define KEY_LESS -1
#define KEY_EQUAL 0
#define KEY_GREATER 1

// Forward declarations
typedef struct bw_tree bw_tree_t;
typedef struct bw_node bw_node_t;
typedef struct bw_page bw_page_t;
typedef struct delta_record delta_record_t;
typedef struct mapping_entry mapping_entry_t;

// Key-value pair structure
typedef struct {
    uint16_t key_len;
    uint16_t value_len;
    char data[]; // key + value stored together
} kv_pair_t;

// Delta record for incremental updates
typedef struct delta_record {
    uint8_t type;           // DELTA_INSERT, DELTA_DELETE, etc.
    uint64_t logical_id;    // Logical page ID this delta applies to
    uint64_t physical_id;   // Physical location of base page
    
    // Delta-specific data
    union {
        struct {            // For INSERT/UPDATE/DELETE
            kv_pair_t* kv;
        } modify;
        
        struct {            // For SPLIT
            uint64_t new_page_id;
            char* split_key;
            uint16_t split_key_len;
        } split;
        
        struct {            // For MERGE
            uint64_t merged_page_id;
        } merge;
    } data;
    
    struct delta_record* next;
} delta_record_t;

// Physical page structure
typedef struct bw_page {
    uint64_t page_id;       // Physical page ID
    uint8_t node_type;      // NODE_TYPE_LEAF or NODE_TYPE_INNER
    uint16_t key_count;     // Number of keys in this page
    uint16_t free_space;    // Available space in bytes
    bool is_dirty;          // Modified flag
    
    // Page data
    char data[PAGE_SIZE - 32]; // Keys and values stored here
    
    // Metadata
    uint64_t lsn;           // Log sequence number for recovery
    uint64_t timestamp;     // Creation/modification time
} bw_page_t;

// Mapping table entry (logical to physical mapping)
typedef struct mapping_entry {
    uint64_t logical_id;    // Logical page ID
    uint64_t physical_id;   // Physical page ID or delta chain head
    delta_record_t* delta_chain; // Chain of delta records
    pthread_rwlock_t lock;  // Reader-writer lock for this mapping
    
    struct mapping_entry* next; // Hash table collision chain
} mapping_entry_t;

// Bw-Tree node (in-memory representation)
typedef struct bw_node {
    uint64_t logical_id;    // Logical node ID
    uint8_t node_type;      // NODE_TYPE_LEAF or NODE_TYPE_INNER
    uint16_t key_count;     // Number of keys
    bool is_consolidated;   // Whether deltas have been consolidated
    
    // Keys and values/children
    char** keys;            // Array of key pointers
    uint16_t* key_lengths;  // Array of key lengths
    
    union {
        struct {            // For leaf nodes
            char** values;  // Array of value pointers
            uint16_t* value_lengths; // Array of value lengths
        } leaf;
        
        struct {            // For inner nodes
            uint64_t* children; // Array of child logical IDs
        } inner;
    } data;
    
    // Metadata
    uint64_t epoch;         // For memory reclamation
    struct bw_node* next_sibling; // Right sibling pointer
} bw_node_t;

// Bw-Tree structure
typedef struct bw_tree {
    uint64_t root_id;           // Root logical page ID
    uint64_t next_logical_id;   // Next available logical ID
    
    // Mapping table (logical to physical page mapping)
    mapping_entry_t** mapping_table;
    uint32_t mapping_table_size;
    uint32_t mapping_count;
    
    // Memory and file management
    memory_manager_t* memory_mgr;
    file_system* fs;
    
    // Statistics
    uint64_t total_pages;
    uint64_t leaf_pages;
    uint64_t inner_pages;
    uint64_t delta_count;
    uint64_t split_count;
    uint64_t merge_count;
    uint64_t consolidation_count;
    
    // Configuration
    uint16_t max_keys_per_page;
    uint16_t min_keys_per_page;
    uint32_t consolidation_threshold; // Max deltas before consolidation
    
    // Concurrency control
    pthread_rwlock_t tree_lock;
    pthread_mutex_t id_mutex;       // For logical ID generation
    
    // Cache for frequently accessed pages
    bw_page_t** page_cache;
    uint32_t cache_size;
    uint32_t cache_count;
    pthread_mutex_t cache_mutex;
} bw_tree_t;

// Search result structure
typedef struct {
    bool found;
    char* value;
    uint16_t value_len;
    uint64_t logical_id;    // Page where key was found/should be inserted
    uint16_t position;      // Position within the page
} search_result_t;

// Iterator structure for range queries
typedef struct bw_iterator {
    bw_tree_t* tree;
    uint64_t current_page_id;
    uint16_t current_position;
    char* start_key;
    uint16_t start_key_len;
    char* end_key;
    uint16_t end_key_len;
    bool ascending;
    bool valid;
} bw_iterator_t;

// Storage engine API
bw_tree_t* storage_init(memory_manager_t* memory_mgr, file_system* fs);
int storage_cleanup(bw_tree_t* tree);

// Basic operations
int storage_insert(bw_tree_t* tree, const char* key, uint16_t key_len, 
                  const char* value, uint16_t value_len);
int storage_delete(bw_tree_t* tree, const char* key, uint16_t key_len);
int storage_update(bw_tree_t* tree, const char* key, uint16_t key_len, 
                  const char* value, uint16_t value_len);
search_result_t storage_search(bw_tree_t* tree, const char* key, uint16_t key_len);

// Range operations
bw_iterator_t* storage_range_search(bw_tree_t* tree, const char* start_key, uint16_t start_key_len,
                                   const char* end_key, uint16_t end_key_len, bool ascending);
bool storage_iterator_next(bw_iterator_t* iter);
kv_pair_t* storage_iterator_get(bw_iterator_t* iter);
void storage_iterator_free(bw_iterator_t* iter);

// Page management
bw_page_t* storage_load_page(bw_tree_t* tree, uint64_t physical_id);
int storage_store_page(bw_tree_t* tree, bw_page_t* page);
bw_node_t* storage_consolidate_page(bw_tree_t* tree, uint64_t logical_id);
int storage_split_page(bw_tree_t* tree, uint64_t logical_id, char* split_key, uint16_t split_key_len);

// Mapping table operations
mapping_entry_t* storage_get_mapping(bw_tree_t* tree, uint64_t logical_id);
int storage_update_mapping(bw_tree_t* tree, uint64_t logical_id, uint64_t physical_id);
int storage_add_delta(bw_tree_t* tree, uint64_t logical_id, delta_record_t* delta);

// Utility functions
int storage_compare_keys(const char* key1, uint16_t len1, const char* key2, uint16_t len2);
uint32_t storage_hash_key(const char* key, uint16_t key_len);
uint64_t storage_generate_logical_id(bw_tree_t* tree);
kv_pair_t* storage_create_kv_pair(const char* key, uint16_t key_len, 
                                 const char* value, uint16_t value_len);

// Statistics and debugging
void storage_print_stats(const bw_tree_t* tree);
void storage_print_tree_structure(bw_tree_t* tree);
int storage_validate_tree(bw_tree_t* tree);

// Persistence and recovery
int storage_flush_dirty_pages(bw_tree_t* tree);
int storage_checkpoint(bw_tree_t* tree);
int storage_recover(bw_tree_t* tree);

// Memory management integration
int storage_register_memory_pools(bw_tree_t* tree);
void storage_cleanup_memory_pools(bw_tree_t* tree);

#endif // STORAGE_ENGINE_H